如果你來自 Express 的世界,你可能習慣了自由定義路由的方式。想要一個登入端點?就寫 POST /login。需要取得用戶資料?那就 GET /getUserInfo。每個路由都是根據功能命名,直觀且靈活。在 Spring Boot 中,你可能用 @GetMapping("/api/users/search") 來處理搜尋,用 @PostMapping("/api/users/activate") 來啟用帳號。FastAPI 讓你用 Python 的函式裝飾器定義任何你想要的路徑結構。
今天我們要探討的是 Rails 如何用完全不同的思維來設計路由系統。Rails 不是限制你的創意,而是提供了一種經過二十年驗證的模式,讓你的 API 更一致、更可預測、更容易維護。當你真正理解 REST 的資源思維後,你會發現那些看似任意的路由命名,其實都在試圖表達同一個概念:對資源的操作。
這個知識點在我們最終的 LMS 系統中無處不在。課程、章節、課時、作業、討論,這些都是資源。學生註冊課程、提交作業、發表評論,這些都是對資源的操作。RESTful 路由不只是技術規範,更是一種組織業務邏輯的思維框架。
讓我們先看看不同框架處理「使用者管理」的典型方式:
// Express 的動作導向設計
app.post('/api/createUser', createUser)
app.get('/api/getUserById/:id', getUserById)
app.put('/api/updateUser/:id', updateUser)
app.delete('/api/deleteUser/:id', deleteUser)
app.get('/api/searchUsers', searchUsers)
app.post('/api/activateUser/:id', activateUser)
// Spring Boot 的服務導向設計
@RestController
@RequestMapping("/api")
public class UserController {
    @PostMapping("/users/register")
    public User registerUser(@RequestBody UserDto user) {}
    
    @GetMapping("/users/profile/{id}")
    public UserProfile getUserProfile(@PathVariable Long id) {}
    
    @PutMapping("/users/settings/{id}")
    public void updateSettings(@PathVariable Long id, @RequestBody Settings settings) {}
}
這些設計沒有錯,但它們把每個操作都當作獨立的動作。Rails 選擇了不同的視角:
# Rails 的資源導向設計
Rails.application.routes.draw do
  resources :users do
    member do
      post :activate
    end
    collection do
      get :search
    end
  end
end
# 這會生成以下路由:
# GET    /users           # index   - 列出所有使用者
# GET    /users/new       # new     - 顯示新建表單(API 模式通常省略)
# POST   /users           # create  - 建立新使用者
# GET    /users/:id       # show    - 顯示特定使用者
# GET    /users/:id/edit  # edit    - 顯示編輯表單(API 模式通常省略)
# PATCH  /users/:id       # update  - 更新使用者
# DELETE /users/:id       # destroy - 刪除使用者
# POST   /users/:id/activate  # activate - 啟用使用者(自定義成員動作)
# GET    /users/search        # search   - 搜尋使用者(自定義集合動作)
Rails 對 REST 的堅持不是教條主義,而是基於實際經驗的設計決策。這個決策帶來了幾個深遠的影響:
一致性帶來的可預測性:當團隊中的每個人都知道 resources :courses 會產生什麼路由,溝通成本大幅降低。新加入的開發者不需要查文件就能猜出大部分 API 的結構。
約束促進更好的設計:當你發現很難用 REST 表達某個功能時,通常意味著你需要重新思考資源的邊界。例如,「發送郵件」這個動作,在 REST 中會變成「建立一個郵件發送任務」:
# 不好的設計:動作導向
post '/api/send_email'
# 好的設計:資源導向
# 把郵件發送當作資源
resources :email_deliveries, only: [:create, :show]
# POST /email_deliveries     - 建立發送任務
# GET  /email_deliveries/:id - 查詢發送狀態
狀態機的自然表達:許多業務邏輯本質上是狀態轉換。REST 的資源模型能優雅地表達這些轉換:
# 訂單狀態管理
resources :orders do
  member do
    patch :pay     # 從 pending 轉為 paid
    patch :ship    # 從 paid 轉為 shipped
    patch :cancel  # 轉為 cancelled
  end
end
在 Rails 中,最基本的路由宣告incredibly簡潔:
Rails.application.routes.draw do
  namespace :api do
    namespace :v1 do
      resources :courses
      resources :users
      resources :enrollments
    end
  end
end
但這簡單的宣告背後,Rails 為你做了大量的工作:
# 讓我們深入了解 resources 實際產生的內容
Rails.application.routes.draw do
  resources :courses
end
# 相當於手動定義:
get    '/courses',          to: 'courses#index',   as: :courses
get    '/courses/new',      to: 'courses#new',     as: :new_course
post   '/courses',          to: 'courses#create'
get    '/courses/:id',      to: 'courses#show',    as: :course
get    '/courses/:id/edit', to: 'courses#edit',    as: :edit_course
patch  '/courses/:id',      to: 'courses#update'
put    '/courses/:id',      to: 'courses#update'
delete '/courses/:id',      to: 'courses#destroy'
LMS 系統中充滿了階層關係。課程包含章節,章節包含課時,課程有很多學生註冊。這些關係如何在路由中表達?
Rails.application.routes.draw do
  resources :courses do
    resources :chapters do
      resources :lessons
    end
    resources :enrollments
    resources :reviews
  end
end
# 這會產生:
# GET /courses/:course_id/chapters
# GET /courses/:course_id/chapters/:chapter_id/lessons
# POST /courses/:course_id/enrollments
但是,過深的巢狀會讓 URL 變得冗長且難以管理。Rails 提供了 shallow routing 來解決這個問題:
Rails.application.routes.draw do
  resources :courses do
    resources :chapters, shallow: true do
      resources :lessons, shallow: true
    end
  end
end
# 產生更簡潔的路由:
# GET    /courses/:course_id/chapters     - 列出課程的所有章節
# POST   /courses/:course_id/chapters     - 為課程建立新章節
# GET    /chapters/:id                    - 顯示特定章節(不需要 course_id)
# PATCH  /chapters/:id                    - 更新章節
# DELETE /chapters/:id                    - 刪除章節
# GET    /chapters/:chapter_id/lessons    - 列出章節的所有課時
# GET    /lessons/:id                     - 顯示特定課時
這種設計體現了一個重要原則:建立時需要上下文,存取時可以獨立。
標準的七個動作不總是足夠的。Rails 區分了兩種自定義路由:
resources :courses do
  member do
    # 作用於特定資源實例
    post :enroll      # POST /courses/:id/enroll
    post :publish     # POST /courses/:id/publish
    get :certificate  # GET  /courses/:id/certificate
  end
  
  collection do
    # 作用於資源集合
    get :popular      # GET /courses/popular
    get :recommended  # GET /courses/recommended
    post :import      # POST /courses/import
  end
end
選擇 member 還是 collection 的關鍵在於:這個動作是針對特定實例還是整個集合?
讓我們為 LMS 系統設計完整的路由結構,展示如何用 RESTful 思維組織複雜的業務邏輯:
Rails.application.routes.draw do
  namespace :api do
    namespace :v1 do
      # 使用者認證(這裡 sessions 被當作資源)
      resources :sessions, only: [:create, :destroy]
      resources :registrations, only: [:create]
      
      # 使用者管理
      resources :users do
        member do
          patch :activate
          patch :deactivate
          post :reset_password
        end
        collection do
          get :instructors  # 獲取所有講師
        end
      end
      
      # 課程管理 - 核心資源
      resources :courses do
        member do
          post :publish
          post :archive
          get :preview
        end
        collection do
          get :featured
          get :trending
        end
        
        # 巢狀資源 - 使用 shallow routing
        resources :chapters, shallow: true do
          member do
            patch :reorder  # 調整章節順序
          end
          
          resources :lessons, shallow: true do
            member do
              post :complete    # 標記課時完成
              get :transcript   # 獲取影片字幕
            end
            
            # 課時的附件
            resources :materials, shallow: true
          end
        end
        
        # 註冊管理 - 關聯但獨立的資源
        resources :enrollments, shallow: true do
          member do
            patch :suspend
            patch :resume
            get :progress     # 學習進度
            get :certificate  # 結業證書
          end
        end
        
        # 作業系統
        resources :assignments, shallow: true do
          resources :submissions, shallow: true do
            member do
              post :grade   # 評分
              post :return  # 退回重做
            end
          end
        end
        
        # 討論區
        resources :discussions, shallow: true do
          resources :posts, shallow: true do
            member do
              post :upvote
              post :pin
            end
          end
        end
        
        # 評價系統
        resources :reviews, shallow: true
      end
      
      # 搜尋功能 - 特殊的資源集合
      namespace :search do
        resources :courses, only: [:index]
        resources :users, only: [:index]
        resources :discussions, only: [:index]
      end
      
      # 分析報表 - 唯讀資源
      namespace :analytics do
        resources :course_reports, only: [:index, :show]
        resources :student_reports, only: [:index, :show]
        resources :engagement_metrics, only: [:index]
      end
    end
  end
end
有些業務邏輯看似不適合 REST,但通過重新思考,我們總能找到優雅的表達方式:
# 場景 1:批次操作
# 不好的設計
post '/api/courses/batch_update'
# 好的設計:把批次操作當作資源
resources :course_batch_operations, only: [:create, :show]
# POST /course_batch_operations - 建立批次操作
# GET  /course_batch_operations/:id - 查詢操作進度
# 場景 2:複雜的搜尋
# 不好的設計
get '/api/searchCoursesWithFilters'
# 好的設計:搜尋結果作為資源
resources :course_searches, only: [:create, :show] do
  member do
    get :results
  end
end
# POST /course_searches - 建立搜尋(保存搜尋條件)
# GET  /course_searches/:id/results - 獲取搜尋結果
# 場景 3:工作流程
# 不好的設計
post '/api/submitAndApproveAssignment'
# 好的設計:分解為獨立的資源操作
resources :assignment_submissions do
  member do
    patch :submit   # 學生提交
    patch :review   # 進入審核
    patch :approve  # 講師批准
    patch :reject   # 講師拒絕
  end
end
Rails 提供了強大的路由約束功能,讓我們能實現複雜的路由邏輯:
Rails.application.routes.draw do
  # API 版本控制
  namespace :api do
    # 版本 1 - 穩定版
    namespace :v1 do
      resources :courses
    end
    
    # 版本 2 - 實驗性功能
    namespace :v2, defaults: { format: :json } do
      resources :courses do
        # V2 新增的 AI 功能
        member do
          post :generate_quiz
          post :summarize
        end
      end
    end
  end
  
  # 基於子域名的路由
  constraints subdomain: 'api' do
    resources :courses
  end
  
  # 基於請求格式的約束
  resources :courses, constraints: { format: :json }
  
  # 自定義約束類
  class BetaUserConstraint
    def self.matches?(request)
      user = User.find_by(token: request.headers['Authorization'])
      user&.beta_tester?
    end
  end
  
  constraints BetaUserConstraint do
    namespace :beta do
      resources :ai_features
    end
  end
  
  # 動態路由約束
  resources :courses do
    # 只有已發布的課程才有這些路由
    constraints -> (request) { Course.find(request.params[:id]).published? } do
      member do
        post :enroll
        get :preview
      end
    end
  end
end
路由是 API 的合約,必須嚴格測試:
# spec/routing/courses_routing_spec.rb
require 'rails_helper'
RSpec.describe "Courses routing", type: :routing do
  describe "standard RESTful routes" do
    it "routes to #index" do
      expect(get: "/api/v1/courses").to route_to(
        controller: "api/v1/courses",
        action: "index"
      )
    end
    
    it "routes to #show" do
      expect(get: "/api/v1/courses/1").to route_to(
        controller: "api/v1/courses",
        action: "show",
        id: "1"
      )
    end
    
    it "routes to #create" do
      expect(post: "/api/v1/courses").to route_to(
        controller: "api/v1/courses",
        action: "create"
      )
    end
  end
  
  describe "custom member routes" do
    it "routes to #publish" do
      expect(post: "/api/v1/courses/1/publish").to route_to(
        controller: "api/v1/courses",
        action: "publish",
        id: "1"
      )
    end
  end
  
  describe "nested resources" do
    it "routes to chapters#index with course_id" do
      expect(get: "/api/v1/courses/1/chapters").to route_to(
        controller: "api/v1/chapters",
        action: "index",
        course_id: "1"
      )
    end
  end
  
  describe "shallow routes" do
    it "routes directly to chapter#show without course_id" do
      expect(get: "/api/v1/chapters/1").to route_to(
        controller: "api/v1/chapters",
        action: "show",
        id: "1"
      )
    end
  end
end
Rails 提供了內建工具來檢視路由:
# 在 console 中檢視所有路由
Rails.application.routes.routes.map do |route|
  {
    method: route.verb,
    path: route.path.spec.to_s,
    controller: route.defaults[:controller],
    action: route.defaults[:action]
  }
end
# 使用 rake 任務
# rake routes
# 或
# rails routes
# 只看特定控制器的路由
# rails routes -c courses
# 搜尋特定路由
# rails routes -g enroll
最常見的誤解是認為每個資源都必須對應一個資料表。實際上,資源是業務概念的抽象:
# SessionsController 管理登入狀態 - 沒有對應的資料表
class Api::V1::SessionsController < ApplicationController
  def create
    user = User.find_by(email: params[:email])
    if user&.authenticate(params[:password])
      token = generate_jwt_token(user)
      render json: { token: token }
    else
      render json: { error: 'Invalid credentials' }, status: :unauthorized
    end
  end
  
  def destroy
    # 使 token 失效的邏輯
    head :no_content
  end
end
# SearchesController 管理搜尋 - 可能跨多個資料表
class Api::V1::SearchesController < ApplicationController
  def create
    search = SearchService.new(search_params)
    results = search.execute
    
    # 可選:儲存搜尋歷史
    SearchHistory.create(
      user: current_user,
      query: search_params,
      results_count: results.count
    )
    
    render json: results
  end
end
選擇正確的 HTTP 動詞不只是技術規範,更是溝通意圖:
# GET - 安全且冪等,不應有副作用
get '/courses/:id/preview'  # 只讀取,不改變狀態
# POST - 不冪等,每次調用可能產生不同結果
post '/courses/:id/enroll'  # 重複註冊可能失敗
# PUT/PATCH - 冪等,多次調用結果相同
patch '/courses/:id'  # 多次更新同樣內容,結果一致
# DELETE - 冪等,刪除已刪除的資源應返回成功
delete '/courses/:id'  # 資源不存在時仍返回 204
RESTful API 通過狀態碼傳達操作結果:
class Api::V1::CoursesController < ApplicationController
  def create
    course = Course.new(course_params)
    
    if course.save
      # 201 Created - 資源成功建立
      render json: course, status: :created, location: api_v1_course_url(course)
    else
      # 422 Unprocessable Entity - 請求格式正確但無法處理
      render json: { errors: course.errors }, status: :unprocessable_entity
    end
  end
  
  def update
    course = Course.find(params[:id])
    
    if course.update(course_params)
      # 200 OK - 成功且有回應內容
      render json: course
    else
      render json: { errors: course.errors }, status: :unprocessable_entity
    end
  end
  
  def destroy
    course = Course.find(params[:id])
    course.destroy
    
    # 204 No Content - 成功但無回應內容
    head :no_content
  end
  
  def enroll
    course = Course.find(params[:id])
    enrollment = current_user.enrollments.build(course: course)
    
    if enrollment.save
      render json: enrollment, status: :created
    elsif enrollment.errors[:course].include?("already enrolled")
      # 409 Conflict - 請求與資源當前狀態衝突
      render json: { error: "Already enrolled" }, status: :conflict
    else
      render json: { errors: enrollment.errors }, status: :unprocessable_entity
    end
  end
end
練習目標:理解基本的 RESTful 路由設計,掌握巢狀資源和自定義動作的使用。
需求說明:
設計一個簡單的部落格系統,包含以下功能:
設計思考點:
解答:
Rails.application.routes.draw do
  namespace :api do
    namespace :v1 do
      # 文章資源 - 核心資源
      resources :posts do
        # 成員路由 - 作用於特定文章
        member do
          patch :publish    # PATCH /api/v1/posts/:id/publish
          patch :unpublish  # PATCH /api/v1/posts/:id/unpublish
        end
        
        # 集合路由 - 作用於文章集合
        collection do
          get :published   # GET /api/v1/posts/published - 獲取所有已發布文章
          get :drafts      # GET /api/v1/posts/drafts - 獲取所有草稿
          get :search      # GET /api/v1/posts/search?q=keyword
        end
        
        # 評論 - 使用 shallow routing 優化 URL
        # 建立評論需要文章 context,但讀取/更新/刪除可以獨立進行
        resources :comments, shallow: true do
          member do
            patch :approve  # 批准評論(如果有審核機制)
            patch :spam     # 標記為垃圾評論
          end
        end
        
        # 文章與標籤的關聯 - 透過獨立的關聯資源管理
        resources :taggings, only: [:index, :create, :destroy]
        # GET    /api/v1/posts/:post_id/taggings - 查看文章的所有標籤
        # POST   /api/v1/posts/:post_id/taggings - 為文章添加標籤
        # DELETE /api/v1/posts/:post_id/taggings/:id - 移除文章的標籤
      end
      
      # 標籤資源 - 獨立管理所有標籤
      resources :tags, only: [:index, :create, :show, :update, :destroy] do
        member do
          get :posts  # GET /api/v1/tags/:id/posts - 獲取該標籤的所有文章
        end
        collection do
          get :popular  # GET /api/v1/tags/popular - 熱門標籤
        end
      end
      
      # 獨立的評論管理(可選,用於管理介面)
      resources :comments, only: [:index] do
        collection do
          get :pending   # 待審核的評論
          get :recent    # 最新評論
        end
      end
    end
  end
end
設計說明:
文章資源的設計理由:
publish 和 unpublish 作為 member 路由,因為它們作用於特定文章published 和 drafts 作為 collection 路由,返回特定狀態的文章集合評論的 shallow routing:
POST /posts/:post_id/comments
PATCH /comments/:id
/posts/:post_id/comments/:id
標籤關聯的處理:
taggings 作為關聯資源,明確表達「文章與標籤的關聯」這個概念常見錯誤:
POST /posts/:id/publish,應該用 PATCH,因為這是更新狀態/posts/:post_id/comments/:comment_id/replies/:reply_id
挑戰目標:設計複雜的工作流程路由,處理多角色互動和版本管理。
需求說明:
為 LMS 系統設計完整的作業提交和批改流程:
設計思考點:
解答:
Rails.application.routes.draw do
  namespace :api do
    namespace :v1 do
      resources :courses do
        # 作業屬於特定課程
        resources :assignments, shallow: true do
          member do
            # 講師操作
            patch :publish      # 發布作業(學生可見)
            patch :close        # 關閉提交(過了截止時間)
            patch :extend       # 延長截止時間
            get :statistics     # 查看提交統計
            
            # 學生操作
            get :requirements   # 查看作業要求詳情
            get :rubric        # 查看評分標準
          end
          
          collection do
            get :upcoming      # 即將到期的作業
            get :overdue       # 已過期的作業
          end
          
          # 作業附件(參考資料、範例等)
          resources :attachments, only: [:index, :create, :destroy], shallow: true
          
          # 作業提交 - 核心工作流程
          resources :submissions, shallow: true do
            member do
              # 狀態轉換(工作流程)
              patch :submit       # 學生提交(draft -> submitted)
              patch :withdraw     # 學生撤回(submitted -> draft)
              patch :start_review # 開始批改(submitted -> reviewing)
              patch :request_revision # 要求修改(reviewing -> revision_requested)
              patch :resubmit     # 重新提交(revision_requested -> submitted)
              patch :grade        # 完成批改並給分(reviewing -> graded)
              patch :finalize     # 最終確認(graded -> finalized)
              
              # 查詢操作
              get :feedback       # 查看批改回饋
              get :similarity     # 查看相似度檢測結果(防抄襲)
            end
            
            collection do
              get :my_submissions # 學生查看自己的所有提交
              get :pending_review # 講師查看待批改的提交
              get :reviewed       # 講師查看已批改的提交
            end
            
            # 版本管理 - 每次提交可以有多個版本
            resources :versions, only: [:index, :show, :create] do
              member do
                patch :restore    # 恢復到特定版本
                get :diff         # 查看與前一版本的差異
              end
            end
            
            # 批改評語和評分 - 作為獨立資源
            resource :grade_record, only: [:show, :create, :update] do
              member do
                patch :approve    # 審核通過評分
                patch :dispute    # 學生對評分提出異議
              end
            end
            
            # 提交的附件(學生上傳的作業檔案)
            resources :files, only: [:index, :create, :destroy], shallow: true
          end
          
          # 同儕評審設定
          resource :peer_review_setting, only: [:show, :create, :update] do
            member do
              post :assign_reviewers  # 分配評審者
              get :assignments        # 查看評審分配情況
            end
          end
        end
      end
      
      # 獨立的同儕評審資源(跨作業管理)
      resources :peer_reviews, only: [:index, :show, :create, :update] do
        member do
          patch :complete    # 完成評審
          patch :skip        # 跳過(無法完成)
          get :rubric        # 查看評審標準
        end
        
        collection do
          get :my_reviews    # 我需要完成的評審
          get :received      # 我收到的評審
        end
        
        # 評審評論
        resources :review_comments, only: [:create, :update, :destroy], shallow: true
      end
      
      # 作業模板(講師可以重複使用)
      resources :assignment_templates, only: [:index, :show, :create, :update, :destroy] do
        member do
          post :duplicate    # 複製模板
          post :create_assignment  # 從模板建立作業
        end
      end
    end
  end
end
設計說明:
核心設計理念:
工作流程的路由設計:
# 使用 PATCH 動詞表達狀態轉換
patch :submit       # draft -> submitted
patch :start_review # submitted -> reviewing
patch :grade        # reviewing -> graded
# 每個狀態轉換都是明確的業務動作
# 不使用通用的 update,而是具體的動作名稱
Shallow Routing 的應用:
# 建立時需要上下文
POST /courses/:course_id/assignments/:assignment_id/submissions
# 存取時可以獨立
GET /submissions/:id
PATCH /submissions/:id/grade
權限控制的考量:
# 在控制器中實現權限檢查
class SubmissionsController < ApplicationController
  before_action :ensure_student, only: [:create, :submit, :withdraw]
  before_action :ensure_instructor, only: [:grade, :request_revision]
  before_action :ensure_owner_or_instructor, only: [:show]
end
常見的設計陷阱與解決方案:
陷阱 1:過度巢狀
# 錯誤:太深的巢狀
/courses/:id/assignments/:id/submissions/:id/versions/:id/files/:id
# 正確:使用 shallow routing
/files/:id  # 文件有唯一 ID,不需要完整路徑
陷阱 2:動作思維
# 錯誤:RPC 風格
post '/submit_assignment'
post '/grade_submission'
# 正確:資源導向
patch '/submissions/:id/submit'
patch '/submissions/:id/grade'
陷阱 3:狀態混淆
# 錯誤:直接修改狀態
patch '/submissions/:id', { status: 'graded' }
# 正確:明確的業務動作
patch '/submissions/:id/grade', { score: 85, feedback: '...' }
擴展性考量:
這個設計展示了如何用 RESTful 方式處理複雜的業務工作流程,同時保持 URL 的清晰和可預測性。
Day 2 的專案結構:今天學習的路由設計直接影響了 config/routes.rb 的組織方式。良好的路由設計能讓專案結構更清晰。
Day 3 的 MVC 架構:路由是 MVC 的入口點,決定了請求如何流向控制器。RESTful 路由確保控制器的動作有明確的職責。
Day 4 的 ActiveRecord:資源導向的路由設計往往能指導我們更好地設計模型關係。如果路由很複雜,可能意味著模型設計需要重新考慮。
Day 6 的控制器設計:明天我們會深入探討控制器如何處理這些路由。RESTful 路由的七個標準動作會對應到控制器的七個方法。
Day 11 的 API 版本控制:今天初步接觸的命名空間會在版本控制中發揮關鍵作用。
Day 22-23 的 LMS 實戰:今天設計的路由結構將成為整個 LMS 系統的骨架。
今天我們探索了 Rails 的 RESTful 路由設計,這不只是學習一個框架的功能,更是理解一種設計哲學。
知識層面,我們學會了如何使用 resources 宣告路由,理解了巢狀路由、淺層路由、成員路由和集合路由的使用場景。我們也學會了如何用路由約束實現複雜的路由邏輯。
思維層面,我們理解了從動作思維到資源思維的轉變。這種轉變不是限制,而是一種更高層次的抽象,能幫助我們更好地組織業務邏輯。
實踐層面,我們能夠為複雜的業務系統設計清晰、一致的 API 結構。無論是簡單的 CRUD 操作,還是複雜的工作流程,都能用 RESTful 的方式優雅地表達。
完成今天的學習後,你應該能夠:
resources 快速建立標準的 CRUD 路由深入閱讀:
相關 Gem:
friendly_id: 使用友善的 URL slug 替代數字 IDversionist: 強大的 API 版本控制工具grape: 另一種建構 RESTful API 的選擇明天我們將探討控制器與請求處理流程。如果說今天學習的路由是 API 的地圖,那明天就是學習如何在這張地圖上導航,處理每一個到達的請求。我們會深入理解請求從進入 Rails 到返回響應的完整生命週期,掌握 Strong Parameters 的安全機制,理解如何在控制器中優雅地處理各種情況。
準備好了嗎?讓我們繼續這段旅程,明天見!